/**
 * src/utils/cloudFunctionManager.ts
 * ------------------------------------
 * 云函数调用管理器
 * 提供统一的云函数调用接口，支持超时控制、重试机制、请求去重等功能
 * 创建日期：2025-01-20
 */
import Taro from '@tarojs/taro'
import { errorUtils } from './errorHandler'

interface CloudFunctionCallOptions {
  timeout?: number
  retry?: boolean
  maxRetries?: number
  enableDeduplication?: boolean
}

class CloudFunctionManager {
  private static pendingCalls: Map<string, Promise<any>> = new Map()
  
  /**
   * 统一的云函数调用方法，支持超时、重试、去重
   * @param name 云函数名称
   * @param data 调用参数
   * @param options 调用选项
   * @returns Promise<any> 云函数返回结果
   */
  static async callFunction(
    name: string,
    data: any = {},
    options: CloudFunctionCallOptions = {}
  ): Promise<any> {
    const {
      timeout = 10000,
      retry = true,
      maxRetries = 2,
      enableDeduplication = true
    } = options
    
    // 生成请求唯一标识
    const requestKey = `${name}_${JSON.stringify(data)}`
    
    // 检查是否有相同的请求正在进行
    if (enableDeduplication && this.pendingCalls.has(requestKey)) {
      console.log(`去重云函数调用: ${name}`)
      return this.pendingCalls.get(requestKey)
    }
    
    // 创建新的调用
    const callPromise = this.executeCall(name, data, timeout, retry, maxRetries)
    
    if (enableDeduplication) {
      this.pendingCalls.set(requestKey, callPromise)
    }
    
    try {
      const result = await callPromise
      return result
    } finally {
      // 调用完成后移除
      if (enableDeduplication) {
        this.pendingCalls.delete(requestKey)
      }
    }
  }
  
  /**
   * 执行实际的云函数调用
   * @param name 云函数名称
   * @param data 调用参数
   * @param timeout 超时时间
   * @param retry 是否重试
   * @param maxRetries 最大重试次数
   * @returns Promise<any> 调用结果
   */
  private static async executeCall(
    name: string,
    data: any,
    timeout: number,
    retry: boolean,
    maxRetries: number
  ): Promise<any> {
    const call = async () => {
      const callPromise = Taro.cloud.callFunction({ name, data })
      
      const timeoutPromise = new Promise<never>((_, reject) => {
        setTimeout(() => {
          reject(new Error(`云函数 ${name} 调用超时`))
        }, timeout)
      })
      
      const result = await Promise.race([callPromise, timeoutPromise])
      
      // 检查业务返回结果
      if (result.result && typeof result.result === 'object') {
        if (result.result.success === false) {
          throw new Error(result.result.error || '云函数执行失败')
        }
      }
      
      return result.result
    }
    
    if (retry) {
      return errorUtils.withRetry(call, {
        maxRetries,
        delayMs: 1000
      })
    } else {
      return call()
    }
  }
  
  /**
   * 批量调用云函数
   * @param calls 云函数调用配置数组
   * @returns Promise<any[]> 所有调用结果
   */
  static async batchCallFunctions(
    calls: Array<{
      name: string
      data?: any
      options?: CloudFunctionCallOptions
    }>
  ): Promise<any[]> {
    try {
      const promises = calls.map(call =>
        this.callFunction(call.name, call.data, call.options)
      )
      
      return await Promise.all(promises)
    } catch (error) {
      console.error('批量云函数调用失败:', error)
      throw error
    }
  }
  
  /**
   * 清除所有待处理的请求
   */
  static clearPendingCalls(): void {
    this.pendingCalls.clear()
  }
  
  /**
   * 获取当前待处理请求数量
   * @returns number 待处理请求数量
   */
  static getPendingCallsCount(): number {
    return this.pendingCalls.size
  }
}

export { CloudFunctionManager, type CloudFunctionCallOptions } 